#include <iostream>
#include <stdio.h>
using std::cout;
using std::endl;

#ifndef RoCConfig_H_H
#define RoCConfig_H_H

inline int Align8(int x){
	return (x & 0x7==0)? x : ((x & 0xfffffff8) +8);
}
inline int Align8_(int x){
	return (x & 0x7==0)? x : (x & 0xfffffff8);
}

class RoCCConfig{
    public:
        uint64_t push_rs2 ;
        uint64_t save_rs2 ;
        uint64_t mvm_rs1  ;
        uint64_t mvm_rs2  ;
        uint64_t config   ;
};

class PushConfig{
    public:
        int32_t push_frond;
        int32_t push_start;
        int32_t push_num;
        int32_t save_frond;
        int32_t save_start;
        int32_t save_num;
};

class MVMConfig{
    public:
        int32_t mvm_array_index ;
        int32_t mvm_row_start   ;
        int32_t mvm_row_num     ;
        int32_t mvm_col_start   ;
        int32_t mvm_col_num     ;
        int32_t conf_random     ;
        int32_t conf_wisenum    ;
        int32_t conf_outshift   ;
        int32_t conf_cimshift   ;
};

class ArrayConfig{
    public:
        // uint64_t push_start      ;
        // uint64_t push_num        ;
        // uint64_t save_start      ;
        // uint64_t save_num        ;
        // int32_t mvm_array_index ;
        // int32_t mvm_row_start   ;
        // int32_t mvm_row_num     ;
        // int32_t mvm_col_start   ;
        // int32_t mvm_col_num     ;
        // int32_t conf_random     ;
        // int32_t conf_wisenum    ;
        // int32_t conf_outshift   ;
        // int32_t conf_cimshift   ;
        MVMConfig  mc;
        PushConfig pc;
        RoCCConfig rc;        
        ArrayConfig(int32_t mvm_array_index,int32_t mvm_row_start,int32_t mvm_row_num,
                    int32_t mvm_col_start,  int32_t mvm_col_num,  int32_t conf_random, 
                    int32_t conf_wisenum ,  int32_t conf_outshift,int32_t conf_cimshift
                    ){
                mc.mvm_array_index = mvm_array_index; mc.mvm_row_start = mvm_row_start; mc.mvm_row_num = mvm_row_num;        
                mc.mvm_col_start   = mvm_col_start  ; mc.mvm_col_num   = mvm_col_num  ; mc.conf_random = conf_random;
                mc.conf_wisenum    = conf_wisenum   ; mc.conf_outshift = conf_outshift; mc.conf_cimshift= conf_cimshift;
                
                pc.push_start = Align8_(mvm_row_start);
                pc.push_frond = mvm_row_start - pc.push_start;
                pc.push_num   = Align8(mvm_row_start + mvm_row_num) - pc.push_start;
    
                pc.save_start = Align8_(mvm_col_start);
                pc.save_frond = mvm_col_start - pc.save_start;
                pc.save_num   = Align8(mvm_col_start + mvm_col_num) -pc.save_start;            
    
                rc.push_rs2 = pc.push_start <<11    | pc.push_num;
                rc.save_rs2 = pc.save_start <<11    | pc.save_num;
                rc.mvm_rs1  = mvm_row_num <<16   | mvm_col_num;
                rc.mvm_rs2  = mvm_array_index<<22| mvm_row_start <<11|mvm_col_start;
                rc.config   = conf_random <<23   | conf_wisenum <<16 |
                              conf_outshift <<8  | conf_cimshift;
        };
       
};

// class ArrayConfig{
//     public:
//         uint64_t push_start      ;
//         uint64_t push_num        ;
//         uint64_t save_start      ;
//         uint64_t save_num        ;
//         uint64_t mvm_array_index ;
//         uint64_t mvm_row_start   ;
//         uint64_t mvm_row_num     ;
//         uint64_t mvm_col_start   ;
//         uint64_t mvm_col_num     ;
//         uint64_t conf_random     ;
//         uint64_t conf_wisenum    ;
//         uint64_t conf_outshift   ;
//         uint64_t conf_cimshift   ;
//         RoCCConfig rc;
//         PushConfig pc;
//         void getrc(void){
//             rc.push_rs2 = push_start <<11    | push_num;
//             rc.save_rs2 = save_start <<11    | save_num;
//             rc.mvm_rs1  = mvm_row_num <<16   | mvm_col_num;
//             rc.mvm_rs2  = mvm_array_index<<22| mvm_row_start <<11|mvm_col_start;
//             rc.config   = conf_random <<23   | conf_wisenum <<16 |
//                           conf_outshift <<8  | conf_cimshift;
            
//             pc.push_frond = mvm_row_start - push_start;
//             pc.push_back  = push_start + push_num - mvm_row_start - mvm_row_num ;
//             pc.save_frond = mvm_col_start - save_start;
//             pc.save_back  = save_start + save_num - mvm_col_start - mvm_col_num;
//         };
       
// };
#endif
// class ArrayConfig{
//     public:
//         uint64_t push_start      ;
//         uint64_t push_num        ;
//         uint64_t save_start      ;
//         uint64_t save_num        ;
//         uint64_t mvm_array_index ;
//         uint64_t mvm_row_start   ;
//         uint64_t mvm_row_num     ;
//         uint64_t mvm_col_start   ;
//         uint64_t mvm_col_num     ;
//         uint64_t conf_random     ;
//         uint64_t conf_wisenum    ;
//         uint64_t conf_outshift   ;
//         uint64_t conf_cimshift   ;
//         // RoCCConfig rc;
//         RoCCConfig getrc(void){
//             RoCCConfig rc;
//             rc.push_rs2 = push_start <<11    | push_num;
//             rc.save_rs2 = save_start <<11    | save_num;
//             rc.mvm_rs1  = mvm_row_num <<16   | mvm_col_num;
//             rc.mvm_rs2  = mvm_array_index<<22| mvm_row_start <<11|mvm_col_start;
//             rc.config   = conf_random <<23   | conf_wisenum <<16 |
//                           conf_outshift <<8  | conf_cimshift;
//             return rc;
//         };
// };

// RoCCConfig ArrayConfig::getrc(void){
//     RoCCConfig rc;
//     rc.push_rs2 = push_start <<11    | push_num;
//     rc.save_rs2 = save_start <<11    | save_num;
//     rc.mvm_rs1  = mvm_row_num <<16   | mvm_col_num;
//     rc.mvm_rs2  = mvm_array_index<<22| mvm_row_start <<11|mvm_col_start;
//     rc.config   = conf_random <<23   | conf_wisenum <<16 |
//                   conf_outshift <<8  | conf_cimshift;
//     return rc;
// }

// void ArrayConfig::show_rc(void){
    // cout << rc.push_rs2 <<endl;
    // cout << rc.save_rs2 <<endl;
    // cout << rc.mvm_rs1 <<endl;
    // cout << rc.mvm_rs2 <<endl;
    // cout << rc.config <<endl;
//     printf("%lx\n%lx\n%lx\n%lx\n%lx\n",rc.push_rs2,rc.save_rs2,rc.mvm_rs1,rc.mvm_rs2,rc.config);
// }


//ac2.init();

// int main(){
//     ac1.push_start     = 0; 
//     ac1.push_num       = 488; 
//     ac1.save_start     = 0; 
//     ac1.save_num       = 96; 
//     ac1.mvm_array_index= 0; 
//     ac1.mvm_row_start  = 0; 
//     ac1.mvm_row_num    = 484; 
//     ac1.mvm_col_start  = 0; 
//     ac1.mvm_col_num    = 92; 
//     ac1.conf_random    = 0; 
//     ac1.conf_wisenum   = 1; 
//     ac1.conf_outshift  = 1; 
//     ac1.conf_cimshift  = 0; 
//     //ac1.init();
    
//     ac2.push_start     =  0;
//     ac2.push_num       =  96;
//     ac2.save_start     =  96;
//     ac2.save_num       =  16;
//     ac2.mvm_array_index=  0;
//     ac2.mvm_row_start  =  0;
//     ac2.mvm_row_num    =  92;
//     ac2.mvm_col_start  =  96;
//     ac2.mvm_col_num    =  10;
//     ac2.conf_random    =  0;
//     ac2.conf_wisenum   =  64;
//     ac2.conf_outshift  =  4;
//     ac2.conf_cimshift  =  0;
//     myMap["fc1"].init();
//     myMap["fc2"].init();

//     map<string, ArrayConfig> myMap = {
//         {"fc1",  ac1},
//         {"fc2",  ac2}
//     };

//     return 0;
// }